/*
 * player.c
 *
 *  Created on: 15 nov. 2010
 *      Author: Nicolas Aucouturier, Laurent Reveillere
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stddef.h>
#include <SDL.h>
#include <SDL_image.h>

#include "../include/game.h"
#include "../include/misc.h"

struct s_player {
	int x, y;
	SDL_Surface * directed_img[4];
	enum e_way current_way;
	int nb_bomb; //player number of bomb
	int nb_life; //player number of life
	int bomb_range; //player's bomb power
	int has_key; //check if he took the key
	int has_goal; //check if he can move to the next level
	int has_reached_gate; //check if he reached the closed door
	int has_won;// check if he saved bomberwoman
};

t_player player_init(int bomb_number, int nb_life, int bomb_range) {
	t_player player = malloc(sizeof(*player));
	if (!player)
		error("Memory error");

	player->directed_img[WEST] = load_image(IMG_PLAYER_LEFT);
	player->directed_img[EAST] = load_image(IMG_PLAYER_RIGHT);
	player->directed_img[NORTH] = load_image(IMG_PLAYER_UP);
	player->directed_img[SOUTH] = load_image(IMG_PLAYER_DOWN);

	player->current_way = SOUTH;
	player->nb_bomb = bomb_number;
	player->nb_life = nb_life;
	player->bomb_range = bomb_range;
	player->has_key = 0;
	player->has_goal = 0;
	player->has_reached_gate = 0;
	player->has_won = 0;

	return player;
}

void player_free(t_player player) {
	assert(player);
	int i;
	for (i = 0; i < 4; i++)
		SDL_FreeSurface(player->directed_img[i]);

	free(player);
}

int player_get_x(t_player player) {
	assert(player != NULL);
	return player->x;
}

int player_get_y(t_player player) {
	assert(player != NULL);
	return player->y;
}

void player_set_current_way(t_player player, enum e_way way) {
	assert(player);
	player->current_way = way;
}

int player_get_nb_bomb(t_player player) {
	assert(player);
	return player->nb_bomb;
}

int player_get_bomb_range(t_player player) {
	assert(player);
	return player->bomb_range;
}

void player_inc_nb_bomb(t_player player) {
	assert(player);
	player->nb_bomb += 1;
}

void player_dec_nb_bomb(t_player player) {
	assert(player);
	player->nb_bomb -= 1;
}

void player_dec_bomb_range(t_player player) {
	assert(player);
	if (player->bomb_range > 1) {
		player->bomb_range -= 1;
	}
}

void player_inc_bomb_range(t_player player) {
	assert(player);
	if (player->bomb_range < 9) {
		player->bomb_range += 1;
	}
}

int player_get_nb_life(t_player player) {
	assert(player);
	return player->nb_life;
}

void player_inc_nb_life(t_player player) {
	assert(player);
	if (player->nb_life < 9) {
		player->nb_life += 1;
	}
}

void player_gameover_display(SDL_Surface * screen, t_player player) {
	assert(player);
	if ((player->nb_life) == -1) {
		SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));
		//WHITE SCREEN

		SDL_Rect place;
		place.x = 0;
		place.y = 0;
		SDL_BlitSurface(load_image(IMG_DEFEATED), NULL, screen, &place);
		SDL_UpdateRect(screen, 0, 0, 0, 0);

		SDL_Delay(4000);

		SDL_FreeSurface(screen);
		SDL_Quit(); //Close the game
	}

}

void player_victory_display(SDL_Surface * screen, t_player player) {
	assert(player);
	if (player->has_won == 1) {
		SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));
		//WHITE SCREEN

		SDL_Rect place;
		place.x = 0;
		place.y = 0;
		SDL_BlitSurface(load_image(IMG_VICTORY), NULL, screen, &place);
		SDL_UpdateRect(screen, 0, 0, 0, 0);

		SDL_Delay(4000);

		SDL_FreeSurface(screen);
		SDL_Quit(); //Close the game
	}

}

void player_dec_nb_life(SDL_Surface * screen, t_player player) {

	assert(player);
	if (player->nb_life >= 0)
		player->nb_life -= 1;
	//else
	//game_end_player_dead(screen, 1);//display game over and close the game
}

int player_has_goal(t_player player) {
	return player->has_goal;
}

int player_has_won(t_player player) {
	return player->has_won;
}

void player_dec_has_goal(t_player player) {
	player->has_goal -= 1;
}

int player_has_reached_gate(t_player player) {
	return player->has_reached_gate;
}

void player_dec_reached_gate(t_player player) {
	player->has_reached_gate -= 1;
}

void player_life_display(int x, int y, t_player player, SDL_Surface * screen) {
	assert(player);
	if (player_get_x(player) == x && player_get_y(player) == y) {
		player_dec_nb_life(screen, player);
	}
}

void player_from_map(t_player player, t_map map) {
	int i, j;
	for (i = 0; i < map_get_width(map); i++) {
		for (j = 0; j < map_get_height(map); j++) {
			if (map_get_cell_type(map, i, j) == CELL_PLAYER) {
				player->x = i;
				player->y = j;
			}
		}
	}
}

static int player_move_aux(t_player player, t_map map, int x1, int y1, int x2,
		int y2, SDL_Surface * screen) {

	if (!map_is_inside(map, x1, y1))
		return 0;

	switch (map_get_cell_type(map, x1, y1)) {
	case CELL_SCENERY:
		return 0;
		break;

	case CELL_CASE:
		if ((map_is_inside(map, x1, y1 + 1) || player_get_y(player) + 1
				== map_get_width(map)) && (map_is_inside(map, x1 + 1, y1)
				|| player_get_x(player) + 1 == map_get_width(map))
				&& (map_is_inside(map, x1, y1 - 1) || player_get_y(player) == 0)
				&& (map_is_inside(map, x1 - 1, y1) || player_get_x(player) == 0)
				&& (map_get_cell_type(map, x2, y2) == CELL_EMPTY)) {
			map_set_cell_type(map, x2, y2, CELL_CASE);
			map_set_cell_type(map, x1, y1, CELL_EMPTY);
			return 1;
		}
		return 0;
		break;

	case CELL_BONUS:
		return 1;
		break;
	case CELL_BOMBERWOMAN:
		player->has_won = 1;
		return 1;

		break;
	case CELL_KEY:
		player->has_key = 1;
		break;
	case CELL_GOAL:
		//player->has_goal=1;
		break;

	case CELL_MONSTER:
		player_dec_nb_life(screen, player);
		return 1;
		break;

	case CELL_PLAYER:
		return 0;
		break;
	case CELL_DOOR:
		return 0;
		break;
	case CELL_CLOSED_DOOR:
		if (player->has_key) {
			return 1;
		} else
			return 0;
		break;
	default:
		break;
	}

	// Player has moved
	return 1;
}

int player_move(t_player player, t_map map, SDL_Surface *screen) {
	assert(player);
	assert(map);
	int x = player->x;
	int y = player->y;
	int move = 0;

	switch (player->current_way) {
	case NORTH:
		if (player_move_aux(player, map, x, y - 1, x, y - 2, screen)) {
			player->y--;
			move = 1;
		}
		break;

	case SOUTH:
		if (player_move_aux(player, map, x, y + 1, x, y + 2, screen)) {
			player->y++;
			move = 1;
		}
		break;

	case WEST:
		if (player_move_aux(player, map, x - 1, y, x - 2, y, screen)) {
			player->x--;
			move = 1;
		}
		break;

	case EAST:
		if (player_move_aux(player, map, x + 1, y, x + 2, y, screen)) {
			player->x++;
			move = 1;
		}
		break;
	}

	if (move) {
		map_set_cell_type(map, x, y, CELL_EMPTY);//empty the previous cell
		if (map_get_cell_type(map, player->x, player->y) == CELL_BONUS) {
			switch (map_get_cell_shift_type(map, player->x, player->y)) {
			case BONUS_LIFE:
				player_inc_nb_life(player);
				break;
			case BONUS_BOMB_NB_DEC:
				player_dec_nb_bomb(player);
				break;
			case BONUS_BOMB_NB_INC:
				player_inc_nb_bomb(player);
				break;
			case BONUS_BOMB_RANGE_INC:
				player_inc_bomb_range(player);
				break;
			case BONUS_BOMB_RANGE_DEC:
				player_dec_bomb_range(player);
				break;
			}

		} else if (map_get_cell_type(map, player->x, player->y) == CELL_GOAL) {
			player->has_goal = 1;
		} else if (map_get_cell_type(map, player->x, player->y)
				== CELL_CLOSED_DOOR) {
			player->has_reached_gate = 1;
		}
		map_set_cell_type(map, player->x, player->y, CELL_PLAYER);//the player own the cell
	}
	return move;
}

void player_display(t_player player, SDL_Surface *screen) {
	assert(player);
	assert(player->directed_img[player->current_way]);
	assert(screen);

	SDL_Rect place;
	place.x = player->x * SIZE_BLOC;
	place.y = player->y * SIZE_BLOC;

	SDL_BlitSurface(player->directed_img[player->current_way], NULL, screen,
			&place);
}

int player_has_key(t_player player) {
	assert(player);
	return player->has_key;
}

